/// Copyright 2007-8 Faraday Media
/// 
/// Licensed under the Apache License, Version 2.0 (the "License"); 
/// you may not use this file except in compliance with the License. 
/// You may obtain a copy of the License at 
/// 
///   http://www.apache.org/licenses/LICENSE-2.0 
/// 
/// Unless required by applicable law or agreed to in writing, software 
/// distributed under the License is distributed on an "AS IS" BASIS, 
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
/// See the License for the specific language governing permissions and 
/// limitations under the License.
using System;
using System.CodeDom;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using System.Xml.Serialization;

namespace MetaSharp.XML.Strategies {
  /// <summary>
  /// Strategy providing functionality to handle [XmlText] attributes and this
  /// allow complex elements to contain raw text.
  /// </summary>
  public class TextContentStrategy : BaseStrategy, IPropertyStrategy {
    #region BaseStrategy Members
    /// <summary>
    /// Indiciates that this is a base code strategy.
    /// </summary>
    public override StrategyPriority Priority {
      get { return StrategyPriority.BaseCode; }
    }

    #endregion

    #region IPropertyStrategy Members
    /// <summary>
    /// Determines whether this strategy applies to a property by checking if it has the [XmlText] attribute.
    /// </summary>
    /// <param name="pProp">the property to check</param>
    /// <returns>the strategy applies</returns>
    public bool AppliesToProperty(PropertyInfo pProp) {
      XmlTextAttribute textAttr = AttributeHelper.GetAttribute<XmlTextAttribute>(pProp);

      return textAttr != null;
    }

    /// <summary>
    /// Generats the code necessary to apply this strategy to a property.
    /// </summary>
    /// <param name="pContext">the generation context</param>
    /// <param name="pProp">the property being processed</param>
    /// <param name="pGeneratedProp">the generated property code</param>
    /// <param name="pClass">the class being generated</param>
    public void Apply(GenerationContext pContext, PropertyInfo pProp, CodeMemberProperty pGeneratedProp,
                      CodeTypeDeclaration pClass) {
      pClass.Members.Add(MethodHelper.GenerateCacheField(pProp));

      if (pProp.CanRead) {
        pGeneratedProp.GetStatements.AddRange(MethodHelper.GenerateSimpleGetMethod(
          pProp, delegate(Type pType, object pDefaultValue) {
                   CodeMethodInvokeExpression getInvoke = new CodeMethodInvokeExpression(
                     new CodeThisReferenceExpression(), "GetContentOrDefault",
                     new CodePrimitiveExpression(pDefaultValue));

                   getInvoke.Method.TypeArguments.Add(new CodeTypeReference(pType));
                   return getInvoke;
                 }));
      }
      if (pProp.CanWrite) {
        pGeneratedProp.SetStatements.AddRange(MethodHelper.GenerateSimpleSetMethod(
          pProp, delegate(Type pType, CodeExpression pValueExpr) {
                   CodeMethodInvokeExpression setExpr =
                     new CodeMethodInvokeExpression(
                       new CodeThisReferenceExpression(), "SetContent",
                       pValueExpr
                       );
                   setExpr.Method.TypeArguments.Add(new CodeTypeReference(pType));
                   return setExpr;
                 }));
      }
    }

    #endregion
  }
}
